Cash Out — Confirmation
Finalize an earnings payout. Presto debits the driver's available earnings and records the institution as the paying party.
Call this only after a successful Cash Out — Initialization and after the driver has supplied the OTP from the Presto driver app.
Overview
Confirmation is the point of no return for a Cash Out. On 200 OK:
- The driver's
available_earningsis permanently reduced byamount - A payout record is created against your institution for reconciliation
- The driver receives a notification in the Presto driver app
Hand over the cash only after you receive 200 OK.
Endpoint details
Method: POST
URL: /api/institutions/v1/drivers/earnings/payout/confirm
Purpose: Debit the driver's earnings and record the payout
All API calls require a valid bearer token. See Authentication.
Request specification
Headers
| Header | Required | Description |
|---|---|---|
Authorization | Yes | Bearer {token} |
Content-Type | Yes | application/json |
Idempotency-Key | Yes | UUID v4. Replaying the same key returns the original response instead of paying out twice. |
Request body
| Parameter | Type | Required | Description |
|---|---|---|---|
transaction_reference | string | Yes | The reference returned by the init call |
otp | string | Conditional | The code the driver received in the Presto app. Required when otp_required was true on init |
Example request
// Headers:
// Authorization: Bearer {token}
// Content-Type: application/json
// Idempotency-Key: 2c1d4e6a-77b8-4c9d-91ef-5a3b7c8d9e01
{
"transaction_reference": "EP-4T7M1XC9QD",
"otp": "418320"
}
Response specification
Success response
200 OK{
"data": {
"status": "completed",
"type": "earnings_payout",
"transaction_reference": "EP-4T7M1XC9QD",
"amount": 100.000,
"currency": "LYD",
"timestamp": "2026-09-14T14:35:12Z",
"institution_reference": "IZI-2026-0914-000188",
"driver": {
"uid": "10432",
"name": "MOH... OK...",
"phone": "218920000000"
},
"available_earnings_after": 28.750
}
}
Response fields
| Field | Type | Description |
|---|---|---|
status | string | "completed" |
type | string | Always "earnings_payout" |
transaction_reference | string | Reference of the completed payout |
amount | number | Amount paid out |
currency | string | Currency of the amount |
timestamp | string | ISO 8601 date and time the payout was recorded |
institution_reference | string | Your own reference from the init call, echoed back unchanged |
driver | object | Driver whose earnings were debited |
available_earnings_after | number | Remaining earnings after the payout |
Error responses
404 Not Found{
"message": "Transaction reference not found"
}
409 Conflict — already finalized
{
"message": "Transaction is not pending"
}
410 Gone — hold expired
{
"message": "Transaction has expired"
}
422 Unprocessable Content — wrong OTP
{
"message": "The provided OTP is invalid.",
"errors": {
"otp": [
"The provided OTP is invalid."
]
},
"attempts_remaining": 2
}
429 Too Many Requests — OTP attempts exhausted
{
"message": "Too many invalid OTP attempts. The transaction has been voided."
}
422 Unprocessable Content — the driver's earnings changed since init
{
"message": "The amount may not be greater than the available earnings.",
"errors": {
"amount": [
"The amount may not be greater than the available earnings."
]
}
}
{
"message": "Transaction processing failed"
}
Error handling
| HTTP Status | Error Type | Example Message | When it Occurs / Resolution |
|---|---|---|---|
| 404 | Not found | {"message": "Transaction reference not found"} | Wrong or unknown reference. Do not pay. |
| 409 | Not pending | {"message": "Transaction is not pending"} | Already confirmed or voided. Query transaction status to find out which. |
| 410 | Expired | {"message": "Transaction has expired"} | More than 15 minutes since init. Re-run init. |
| 422 | Invalid OTP | {"message": "The provided OTP is invalid.", "attempts_remaining": 2} | Ask the driver to re-read the code. The hold stays active until attempts run out or the ttl passes. |
| 429 | OTP attempts exhausted | {"message": "Too many invalid OTP attempts. The transaction has been voided."} | The hold is released. Start again with a new init. |
| 422 | Balance changed | {"message": "The amount may not be greater than the available earnings."} | The driver's earnings were reduced through another channel after init. The transaction is now failed. Do not pay. |
| 500 | Internal server error | {"message": "Transaction processing failed"} | Outcome unknown. Query transaction status before paying. |
If confirm times out, the payout may or may not have been recorded. Query transaction status with the same transaction_reference and pay only if it reports completed. Retrying confirm is safe only with the same Idempotency-Key.
Implementation tips
- Allow up to 3 OTP attempts in your teller interface and surface
attempts_remainingto the teller. - Record
transaction_reference,timestampandavailable_earnings_afteragainst your own receipt for end-of-day reconciliation. - Print a receipt showing the Presto reference so the driver can raise a dispute with either party.
- Use exponential backoff for 5xx retries, always with the same idempotency key.
Next steps
Verify or reconcile the payout with the Transaction Status endpoint.